/**
 * @file Logger.h
 * @brief 日志记录器主类，管理日志级别和输出
 * @author Enterprise Logger Team
 * @date 2024
 */

#ifndef LOGGER_LOGGER_H
#define LOGGER_LOGGER_H

#include "LogStream.h"
#include <memory>
#include <functional>
#include <chrono>
#include <atomic>

namespace logger {

// 日志级别枚举
enum class LogLevel
{
    TRACE_LEVEL,
    DEBUG_LEVEL,
    INFO_LEVEL,
    WARN_LEVEL,
    ERROR_LEVEL,
    FATAL_LEVEL,
    NUM_LOG_LEVELS,
};

// 时间戳类
class Timestamp
{
public:
    Timestamp()
        : microSecondsSinceEpoch_(0)
    {}

    explicit Timestamp(int64_t microSecondsSinceEpochArg)
        : microSecondsSinceEpoch_(microSecondsSinceEpochArg)
    {}

    // 获取当前时间
    static Timestamp now()
    {
        auto now = std::chrono::system_clock::now();
        auto micros =
            std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
        return Timestamp(micros);
    }

    // 格式化为字符串
    std::string toString() const;
    std::string toFormattedString(bool showMicroseconds = true) const;

    int64_t microSecondsSinceEpoch() const { return microSecondsSinceEpoch_; }

    static const int kMicroSecondsPerSecond = 1000 * 1000;

private:
    int64_t microSecondsSinceEpoch_;
};

// 源文件位置信息
class SourceFile
{
public:
    template<int N>
    SourceFile(const char (&arr)[N])
        : data_(arr)
        , size_(N - 1)
    {
        const char* slash = strrchr(data_, '/');
        if (!slash) {
            slash = strrchr(data_, '\\');
        }
        if (slash) {
            data_ = slash + 1;
            size_ = static_cast<int>(strlen(data_));
        }
    }

    explicit SourceFile(const char* filename)
        : data_(filename)
    {
        const char* slash = strrchr(filename, '/');
        if (!slash) {
            slash = strrchr(filename, '\\');
        }
        if (slash) {
            data_ = slash + 1;
        }
        size_ = static_cast<int>(strlen(data_));
    }

    const char* data_;
    int         size_;
};

/**
 * @brief 日志记录器类
 * 每条日志对应一个Logger对象
 */
class Logger
{
public:
    typedef std::function<void(const char* msg, int len)> OutputFunc;
    typedef std::function<void()>                         FlushFunc;

    Logger(SourceFile file, int line);
    Logger(SourceFile file, int line, LogLevel level);
    Logger(SourceFile file, int line, LogLevel level, const char* func);
    Logger(SourceFile file, int line, bool toAbort);
    ~Logger();

    // 获取日志流
    LogStream& stream() { return impl_.stream_; }

    // 全局日志级别设置
    static LogLevel logLevel();
    static void     setLogLevel(LogLevel level);

    // 设置输出和刷新函数
    static void setOutput(OutputFunc);
    static void setFlush(FlushFunc);

    // 设置时区
    static void setTimeZone(const char* tz);

private:
    class Impl
    {
    public:
        typedef logger::LogLevel LogLevel;
        Impl(LogLevel level, int old_errno, const SourceFile& file, int line);
        void formatTime();
        void finish();

        Timestamp  time_;
        LogStream  stream_;
        LogLevel   level_;
        int        line_;
        SourceFile basename_;
    };

    Impl impl_;
};

// 全局日志级别
extern std::atomic<logger::LogLevel> g_logLevel;

inline logger::LogLevel Logger::logLevel()
{
    return g_logLevel.load(std::memory_order_acquire);
}

inline void Logger::setLogLevel(logger::LogLevel level)
{
    g_logLevel.store(level, std::memory_order_release);
}

// 便捷宏定义
#define LOG_TRACE                                                    \
    if (logger::Logger::logLevel() <= logger::LogLevel::TRACE_LEVEL) \
    logger::Logger(__FILE__, __LINE__, logger::LogLevel::TRACE_LEVEL, __func__).stream()
#define LOG_DEBUG                                                    \
    if (logger::Logger::logLevel() <= logger::LogLevel::DEBUG_LEVEL) \
    logger::Logger(__FILE__, __LINE__, logger::LogLevel::DEBUG_LEVEL, __func__).stream()
#define LOG_INFO                                                    \
    if (logger::Logger::logLevel() <= logger::LogLevel::INFO_LEVEL) \
    logger::Logger(__FILE__, __LINE__, logger::LogLevel::INFO_LEVEL, __func__).stream()
#define LOG_WARN logger::Logger(__FILE__, __LINE__, logger::LogLevel::WARN_LEVEL, __func__).stream()
#define LOG_ERROR \
    logger::Logger(__FILE__, __LINE__, logger::LogLevel::ERROR_LEVEL, __func__).stream()
#define LOG_FATAL \
    logger::Logger(__FILE__, __LINE__, logger::LogLevel::FATAL_LEVEL, __func__).stream()
#define LOG_SYSERR logger::Logger(__FILE__, __LINE__, false).stream()
#define LOG_SYSFATAL logger::Logger(__FILE__, __LINE__, true).stream()

// 条件日志
#define LOG_IF(cond, level) \
    if (cond) LOG_##level

// 格式化支持
template<typename T> T* CheckNotNull(const char* file, int line, const char* names, T* ptr)
{
    if (ptr == nullptr) {
        Logger(file, line, logger::LogLevel::FATAL_LEVEL).stream() << names;
    }
    return ptr;
}

#define CHECK_NOTNULL(val) \
    ::logger::CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))

}   // namespace logger

#endif   // LOGGER_LOGGER_H
